{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"../imgs/keras-logo-small.jpg\" width=\"20%\" />\n",
    "\n",
    "## Keras: Deep Learning library for Theano and TensorFlow"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    ">Keras is a minimalist, highly modular neural networks library, written in Python and capable of running on top of either TensorFlow or Theano. \n",
    "\n",
    ">It was developed with a focus on enabling fast experimentation. Being able to go from idea to result with the least possible delay is key to doing good research.\n",
    "ref: https://keras.io/"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a name=\"kaggle\"></a>\n",
    "### Kaggle Challenge Data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    ">The Otto Group is one of the world’s biggest e-commerce companies, A consistent analysis of the performance of products is crucial. However, due to diverse global infrastructure, many identical products get classified differently.\n",
    "For this competition, we have provided a dataset with 93 features for more than 200,000 products. The objective is to build a predictive model which is able to distinguish between our main product categories. \n",
    "Each row corresponds to a single product. There are a total of 93 numerical features, which represent counts of different events. All features have been obfuscated and will not be defined any further.\n",
    "\n",
    "https://www.kaggle.com/c/otto-group-product-classification-challenge/data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### For this section we will use the Kaggle Otto Group Challenge Data. You will find these data in \n",
    "`../data/kaggle_ottogroup/` folder."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Logistic Regression\n",
    "\n",
    "This algorithm has nothing to do with the canonical _linear regression_, but it is an algorithm that allows us to solve problems of classification (supervised learning). \n",
    "\n",
    "In fact, to estimate the dependent variable, now we make use of the so-called **logistic function** or **sigmoid**. \n",
    "\n",
    "It is precisely because of this feature we call this algorithm logistic regression.\n",
    "\n",
    "![](../imgs/sigmoid.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Data Preparation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using TensorFlow backend.\n"
     ]
    }
   ],
   "source": [
    "from kaggle_data import load_data, preprocess_data, preprocess_labels\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "9 classes\n",
      "93 dims\n"
     ]
    }
   ],
   "source": [
    "X_train, labels = load_data('../data/kaggle_ottogroup/train.csv', train=True)\n",
    "X_train, scaler = preprocess_data(X_train)\n",
    "Y_train, encoder = preprocess_labels(labels)\n",
    "\n",
    "X_test, ids = load_data('../data/kaggle_ottogroup/test.csv', train=False)\n",
    "X_test, _ = preprocess_data(X_test, scaler)\n",
    "\n",
    "nb_classes = Y_train.shape[1]\n",
    "print(nb_classes, 'classes')\n",
    "\n",
    "dims = X_train.shape[1]\n",
    "print(dims, 'dims')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['Class_1', 'Class_2', 'Class_3', 'Class_4', 'Class_5', 'Class_6',\n",
       "       'Class_7', 'Class_8', 'Class_9'], dtype=object)"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.unique(labels)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.,  0.,  0., ...,  0.,  0.,  0.],\n",
       "       [ 0.,  0.,  0., ...,  1.,  0.,  0.],\n",
       "       [ 0.,  0.,  0., ...,  0.,  0.,  0.],\n",
       "       ..., \n",
       "       [ 0.,  0.,  0., ...,  0.,  0.,  0.],\n",
       "       [ 0.,  0.,  0., ...,  0.,  0.,  0.],\n",
       "       [ 0.,  0.,  1., ...,  0.,  0.,  0.]])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Y_train  # one-hot encoding"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Using Theano"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import theano as th\n",
    "import theano.tensor as T"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1\n",
      "Epoch 2\n",
      "Epoch 3\n",
      "Epoch 4\n",
      "Epoch 5\n",
      "Epoch 6\n",
      "Epoch 7\n",
      "Epoch 8\n",
      "Epoch 9\n",
      "Epoch 10\n",
      "target values for Data:\n",
      "[ 0.  0.  0. ...,  0.  0.  0.]\n",
      "prediction on training set:\n",
      "[ True  True False ...,  True  True  True]\n"
     ]
    }
   ],
   "source": [
    "#Based on example from DeepLearning.net\n",
    "rng = np.random\n",
    "N = 400\n",
    "feats = 93\n",
    "training_steps = 10\n",
    "\n",
    "# Declare Theano symbolic variables\n",
    "x = T.matrix(\"x\")\n",
    "y = T.vector(\"y\")\n",
    "w = th.shared(rng.randn(feats), name=\"w\")\n",
    "b = th.shared(0., name=\"b\")\n",
    "\n",
    "# Construct Theano expression graph\n",
    "p_1 = 1 / (1 + T.exp(-T.dot(x, w) - b))         # Probability that target = 1\n",
    "prediction = p_1 > 0.5                          # The prediction thresholded\n",
    "xent = -y * T.log(p_1) - (1-y) * T.log(1-p_1)   # Cross-entropy loss function\n",
    "cost = xent.mean() + 0.01 * (w ** 2).sum()      # The cost to minimize\n",
    "gw, gb = T.grad(cost, [w, b])                   # Compute the gradient of the cost\n",
    "                                                \n",
    "\n",
    "# Compile\n",
    "train = th.function(\n",
    "          inputs=[x,y],\n",
    "          outputs=[prediction, xent],\n",
    "          updates=((w, w - 0.1 * gw), (b, b - 0.1 * gb)),\n",
    "          allow_input_downcast=True)\n",
    "predict = th.function(inputs=[x], outputs=prediction, allow_input_downcast=True)\n",
    "\n",
    "#Transform for class1\n",
    "y_class1 = []\n",
    "for i in Y_train:\n",
    "    y_class1.append(i[0])\n",
    "y_class1 = np.array(y_class1)\n",
    "\n",
    "# Train\n",
    "for i in range(training_steps):\n",
    "    print('Epoch %s' % (i+1,))\n",
    "    pred, err = train(X_train, y_class1)\n",
    "\n",
    "print(\"target values for Data:\")\n",
    "print(y_class1)\n",
    "print(\"prediction on training set:\")\n",
    "print(predict(X_train))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Using Tensorflow"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import tensorflow as tf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Parameters\n",
    "learning_rate = 0.01\n",
    "training_epochs = 25\n",
    "display_step = 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# tf Graph Input\n",
    "x = tf.placeholder(\"float\", [None, dims]) \n",
    "y = tf.placeholder(\"float\", [None, nb_classes])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor 'Placeholder:0' shape=(?, 93) dtype=float32>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Model (Introducing Tensorboard)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Construct (linear) model\n",
    "with tf.name_scope(\"model\") as scope:\n",
    "    # Set model weights\n",
    "    W = tf.Variable(tf.zeros([dims, nb_classes]))\n",
    "    b = tf.Variable(tf.zeros([nb_classes]))\n",
    "    activation = tf.nn.softmax(tf.matmul(x, W) + b) # Softmax\n",
    "\n",
    "    # Add summary ops to collect data\n",
    "    w_h = tf.summary.histogram(\"weights_histogram\", W)\n",
    "    b_h = tf.summary.histogram(\"biases_histograms\", b)\n",
    "    tf.summary.scalar('mean_weights', tf.reduce_mean(W))\n",
    "    tf.summary.scalar('mean_bias', tf.reduce_mean(b))\n",
    "\n",
    "# Minimize error using cross entropy\n",
    "# Note: More name scopes will clean up graph representation\n",
    "with tf.name_scope(\"cost_function\") as scope:\n",
    "    cross_entropy = y*tf.log(activation)\n",
    "    cost = tf.reduce_mean(-tf.reduce_sum(cross_entropy,reduction_indices=1))\n",
    "    # Create a summary to monitor the cost function\n",
    "    tf.summary.scalar(\"cost_function\", cost)\n",
    "    tf.summary.histogram(\"cost_histogram\", cost)\n",
    "\n",
    "with tf.name_scope(\"train\") as scope:\n",
    "    # Set the Optimizer\n",
    "    optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Accuracy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "with tf.name_scope('Accuracy') as scope:\n",
    "    correct_prediction = tf.equal(tf.argmax(activation, 1), tf.argmax(y, 1))\n",
    "    # Calculate accuracy\n",
    "    accuracy = tf.reduce_mean(tf.cast(correct_prediction, \"float\"))\n",
    "    # Create a summary to monitor the cost function\n",
    "    tf.summary.scalar(\"accuracy\", accuracy)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Learning in a TF Session"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "LOGDIR = \"/tmp/logistic_logs\"\n",
    "import os, shutil\n",
    "if os.path.isdir(LOGDIR):\n",
    "    shutil.rmtree(LOGDIR)\n",
    "os.mkdir(LOGDIR)\n",
    "\n",
    "# Plug TensorBoard Visualisation \n",
    "writer = tf.summary.FileWriter(LOGDIR, graph=tf.get_default_graph())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "model/weights_histogram:0\n",
      "model/biases_histograms:0\n",
      "model/mean_weights:0\n",
      "model/mean_bias:0\n",
      "cost_function/cost_function:0\n",
      "cost_function/cost_histogram:0\n",
      "Accuracy/accuracy:0\n",
      "Tensor(\"add:0\", shape=(), dtype=string)\n"
     ]
    }
   ],
   "source": [
    "for var in tf.get_collection(tf.GraphKeys.SUMMARIES):\n",
    "    print(var.name)\n",
    "    \n",
    "summary_op = tf.summary.merge_all()\n",
    "print('Summary Op: ' + summary_op)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "accuracy epoch 0:0.6649535894393921\n",
      "accuracy epoch 1:0.665276825428009\n",
      "accuracy epoch 2:0.6657131910324097\n",
      "accuracy epoch 3:0.6659556031227112\n",
      "accuracy epoch 4:0.6662949919700623\n",
      "accuracy epoch 5:0.6666181683540344\n",
      "accuracy epoch 6:0.6668121218681335\n",
      "accuracy epoch 7:0.6671029925346375\n",
      "accuracy epoch 8:0.6674585342407227\n",
      "accuracy epoch 9:0.6678463816642761\n",
      "accuracy epoch 10:0.6680726408958435\n",
      "accuracy epoch 11:0.6682504415512085\n",
      "accuracy epoch 12:0.6684605479240417\n",
      "accuracy epoch 13:0.6687514185905457\n",
      "accuracy epoch 14:0.6690422892570496\n",
      "accuracy epoch 15:0.6692523956298828\n",
      "accuracy epoch 16:0.6695109605789185\n",
      "accuracy epoch 17:0.6697695255279541\n",
      "accuracy epoch 18:0.6699796319007874\n",
      "accuracy epoch 19:0.6702220439910889\n",
      "accuracy epoch 20:0.6705452799797058\n",
      "accuracy epoch 21:0.6708361506462097\n",
      "accuracy epoch 22:0.6710785627365112\n",
      "accuracy epoch 23:0.671385645866394\n",
      "accuracy epoch 24:0.6716926693916321\n",
      "Training phase finished\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYwAAAEKCAYAAAAB0GKPAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3Xl8VeW1//HPkuQKRa5ApYoBRVtHIEwRZapWRERQkOpF\nEYtWRX/KT6kFUduqtSq8pE7tr4r8Cg4VwaqAVO1lqkOpEwkEEVJlKLYBrlAgyKgE1v3jnIQQkrBP\nkn3G7/v1yotz9n72Pmtnk6zs53nW3ubuiIiIHM4RiQ5ARERSgxKGiIgEooQhIiKBKGGIiEggShgi\nIhKIEoaIiASihCEiIoEoYYiISCBKGCIiEkhWogOoT8ccc4y3adMm0WGIiKSMgoKCf7t7iyBt0yph\ntGnThvz8/ESHISKSMszsi6Bt1SUlIiKBKGGIiEggShgiIhJIaGMYZtYaeAE4DtgPTHL3Jyu1uRoY\nG327A/g/7r40uu4i4EmgAfB7dx8fVqyS/Pbu3UtxcTF79uxJdCgiKalhw4a0atWK7OzsWu8jzEHv\nUuCn7r7YzJoABWY2z91XVGjzD+Bcd99qZv2AScDZZtYA+B3QBygGFpnZ7ErbSgYpLi6mSZMmtGnT\nBjNLdDgiKcXd2bx5M8XFxZx00km13k9oCcPdNwAboq+3m1kRkAOsqNDm/QqbfAi0ir7uCqxy9zUA\nZjYdGFhx2/oya8k6Jsz5jPUluzm+aSPG9D2NQZ1y6vtjpI727NmjZCFSS2bGt7/9bTZt2lSn/cRl\nDMPM2gCdgI9qaHY98Ofo6xzgXxXWFUeXVbXvEWaWb2b5sX4zZi1Zx90zlrGuZDcOrCvZzd0zljFr\nybqY9iPxoWQhUnv18fMTesIws6OA14BR7v5VNW1+QCRhlI1nVHVkVT5L1t0nuXueu+e1aBGo9qTc\nhDmfsXvvvoOW7d67jwlzPotpPyIimSDUhGFm2USSxVR3n1FNm1zg98BAd98cXVwMtK7QrBWwvr7j\nW1+yO6blktmOOuqoOu9j/fr1XH755dWuLykp4amnngrcvrJrr72Wk046iY4dO9KhQwcWLFhQp3jr\n28SJE3nhhRfqtI9ly5bRsWNHOnbsSPPmzcuP94ILLohpP3379mX79u01tvnZz37G22+/XZdwD6tn\nz54UFhaG+hn1JcxZUgZMBorc/bFq2pwAzACucffPK6xaBJxiZicB64ArgaH1HePxTRuxrorkcHzT\nRvX9URJnyTo2dfzxx/Pqq69Wu74sYdxyyy2B2ldlwoQJXH755bz99tuMGDGClStX1ilmgNLSUrKy\n6v7r4uabb67zPtq3b1/+C/baa69lwIABVSbVw8U8Z86cw37WQw89VPtA01CYVxg9gGuA882sMPp1\nsZndbGZl/2vuBb4NPBVdnw/g7qXASGAOUAT80d2X13eAY/qeRqPsBgcta5TdgDF9T6vvj5I4iufY\n1BdffEHv3r3Jzc2ld+/e/POf/wRg9erVnHPOOZx11lnce++95Vcna9eupV27dgAsX76crl270rFj\nR3Jzc1m5ciV33XUXq1evpmPHjowZM+ag9vv27WP06NG0b9+e3Nxcfvvb39YYW7du3Vi37sAxFxQU\ncO6559KlSxf69u3Lhg0bAFi0aBG5ubl069aNMWPGlH/ec889xxVXXMEll1zChRdeCESS0VlnnUVu\nbi733XcfADt37qR///506NCBdu3a8fLLLwNw1113ceaZZ5Kbm8vo0aMBuP/++/n1r38NQGFhIeec\ncw65ublcdtllbN26FYDzzjuPsWPH0rVrV0499VT++te/Bj4f8+fP54ILLuDKK6+kU6dOAFxyySV0\n6dKFtm3b8vvf/768batWrSgpKWHVqlW0a9eO66+/nrZt29KvX7/y6dvDhg1j1qxZ5e3vv/9+OnXq\nRG5uLp9/Hvkbd+PGjfTu3ZvOnTtzyy23kJOTQ0lJyUFxlZaW0rRpU37yk5/QuXNn+vTpw+bNm8vX\nT58+na5du3Laaafx/vuRuUCrV6+mV69edOrUiS5duvDRR5Eh4HXr1tGzZ086duxIu3btytv/+c9/\nplu3bnTu3JkhQ4awc+fOwN+3wNw9bb66dOnisZq5uNi7j1vgbca+4d3HLfCZi4tj3oeEb8WKFYHb\ndh+3wE8c+8YhX93HLahTDI0bNz5k2YABA/y5555zd/fJkyf7wIED3d29f//+/tJLL7m7+9NPP12+\n7T/+8Q9v27atu7uPHDnSX3zxRXd3//rrr33Xrl0Hra/c/qmnnvLBgwf73r173d198+bNh8QzfPhw\nf+WVV9zdfebMmX7VVVe5u/s333zj3bp1840bN7q7+/Tp0/26665zd/e2bdv63/72N3d3Hzt2bPnn\nPfvss56Tk1P+OXPmzPEbb7zR9+/f7/v27fP+/fv7u+++66+++qrfcMMN5TGUlJT45s2b/dRTT/X9\n+/e7u/vWrVvd3f2+++7zCRMmuLt7+/bt/Z133nF391/84hd+++23u7v7ueee63fccYe7u7/55pve\nu3fvas7Iwcfr7j5v3jxv3Lixf/HFF+XLyuLfuXOnn3HGGb5lyxZ3d8/JyfGtW7f6ypUrPSsryz/5\n5BN3d7/ssst82rRp7u5+9dVX+8yZM8vbP/XUU+7u/uSTT/pNN93k7u433XSTP/LII+7u/qc//cmB\n8uMts3fvXgd8+vTphxxvjx49/M4773R399dff9379u1bHu/u3bvd3b2oqMi7du3q7u7jx4/38ePH\nu7t7aWmpb9++3b/88kv//ve/7zt37nR39wcffNAfeuihQ75fVf0cAfke8HdsWt18sDYGdcpJiq4K\nqT/xHJv64IMPmDEjMjx3zTXXcOedd5YvL/vLdOjQoeV/YVfUrVs3HnroIYqLixk8eDCnnHJKjZ81\nf/58br755vJulubNm1fZbsyYMdx5551s3LiRDz/8EIDPPvuMTz/9lD59+gCRq5WWLVtSUlLC9u3b\n6d69e3msb7zxRvm++vTpU/45c+fOZe7cueV/ue/YsYOVK1fSq1cvRo8ezdixYxkwYAC9evWitLSU\nhg0bcsMNN9C/f38GDBhwUIzbtm2jpKSEc889F4Dhw4dzxRVXlK8fPHgwAF26dGHt2rU1fl8q69at\nGyeccEL5+8cff5zZs2cDkXqe1atXk5eXd9A23/ve92jfvv1hP7NiXG+99RYACxcu5Gc/+xkAAwYM\noEmTJlVum5WVVX6Mw4YNY+jQA73sVR3v119/zciRI1m6dClZWVmsXr0agLPOOoubbrqJPXv2MGjQ\nIDp06MD8+fNZsWJF+Xn85ptv6NmzZ4DvVmx0axBJO9WNQcVjbCqWqYtDhw5l9uzZNGrUiL59+/KX\nv/ylxvbuHmj/EyZMYNWqVTz44IMMHz68fNu2bdtSWFhIYWEhy5YtY+7cuUT+wKxe48aND/r8u+++\nu3wfq1at4vrrr+fUU0+loKCA9u3bc/fdd/PAAw+QlZXFxx9/zA9/+ENmzZrFRRddFOA7csCRRx4J\nQIMGDSgtLY1p24oxz58/n/fee48PP/yQpUuXkpubW+XdAso+73CfWVVch/selql87iq+r2q/jz76\nKK1bt2bZsmV8/PHHfP311wCcf/75vPPOO7Rs2ZKrr76aqVOn4u5cdNFF5edmxYoVTJo0KVBcsVDC\nkLQTz7Gp7t27M336dACmTp1a/lfdOeecw2uvvQZQvr6yNWvWcPLJJ3Pbbbdx6aWX8sknn9CkSZNq\nZ+5ceOGFTJw4sfwXypYtW6qN64gjjuD2229n//79zJkzh9NOO41NmzbxwQcfAJFbrSxfvpxmzZrR\npEmT8iuR6mKFyKyiKVOmsGPHDiDSl75x40bWr1/Pt771LYYNG8bo0aNZvHgxO3bsYNu2bVx88cU8\n8cQTh8wCOvroo2nWrFn5+MQf/vCH8quN+rRt2zaaN29Oo0aNWL58OYsWLar3z+jZsyd//OMfAXjr\nrbeqPX979+4tvxp96aWXDnsFsG3bNlq2bImZ8fzzz5cnpi+++ILjjjuOESNGcO2117JkyRK6d+/O\nu+++y5o1a4DIuFJ9THaoLOO7pGKVrLNv5ICy81Hf52nXrl20atWq/P0dd9zBb37zG3784x8zYcIE\nWrRowbPPPgvAE088wbBhw3j00Ufp378/Rx999CH7e/nll3nxxRfJzs7muOOO495776V58+b06NGD\ndu3a0a9fP2699dby9jfccAOff/45ubm5ZGdnc+ONNzJy5Mhq4zUzfv7zn/PII4/Qt29fXn31VW67\n7Ta2bdtGaWkpo0aNom3btkyePJkbb7yRxo0bc95551UZK0QSVlFREd26dQMi04xffPFFVq1axZgx\nYzjiiCPIzs7m6aefZvv27QwcOJA9e/bg7jz++OOH7O/555/n5ptvZteuXZx88snl37v61L9/fyZN\nmkSHDh04/fTTOfvss+v9M375y18ydOhQpk6dyvnnn8+xxx570FVOmaOPPprFixfz8MMP07x58/LJ\nAdUZOXIkl19+OdOmTeOCCy4ovwpZsGABjz32GNnZ2eXn4Nhjj2Xy5MkMGTKEb775BoCHH374sN2c\nsbKgl1OpIC8vz8N8gFLZ7JuKxX6NshswbnB7JY2QFRUVccYZZyQ6jMB27dpFo0aNMDOmT5/OtGnT\neP311xMdVpV27NhRPotr/PjxbNiwgSeffPIwW0mZPXv2kJWVRVZWFgsXLmTUqFGHPMittLSUY445\n5pDZU/FW1c+RmRW4e141mxxEVxgxqKkyXAlDKiooKGDkyJG4O02bNmXKlCmJDqlab775JuPGjaO0\ntJQTTzyR5557LtEhpZS1a9dy1VVXsW/fPo488kieeeaZRIcUGiWMGKgyXILq1asXS5cuTXQYgQwZ\n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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x11e8e3080>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 5 5 ..., 2 1 1]\n"
     ]
    }
   ],
   "source": [
    "# Launch the graph\n",
    "with tf.Session() as session:\n",
    "    # Initializing the variables\n",
    "    session.run(tf.global_variables_initializer())\n",
    "    \n",
    "    cost_epochs = []\n",
    "    # Training cycle\n",
    "    for epoch in range(training_epochs):\n",
    "        _, summary, c = session.run(fetches=[optimizer, summary_op, cost], \n",
    "                                    feed_dict={x: X_train, y: Y_train})\n",
    "        cost_epochs.append(c)\n",
    "        writer.add_summary(summary=summary, global_step=epoch)\n",
    "        print(\"accuracy epoch {}:{}\".format(epoch, accuracy.eval({x: X_train, y: Y_train})))\n",
    "        \n",
    "    print(\"Training phase finished\")\n",
    "    \n",
    "    #plotting\n",
    "    plt.plot(range(len(cost_epochs)), cost_epochs, 'o', label='Logistic Regression Training phase')\n",
    "    plt.ylabel('cost')\n",
    "    plt.xlabel('epoch')\n",
    "    plt.legend()\n",
    "    plt.show()\n",
    "    \n",
    "    prediction = tf.argmax(activation, 1)\n",
    "    print(prediction.eval({x: X_test}))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Process is terminated.\n"
     ]
    }
   ],
   "source": [
    "%%bash\n",
    "python -m tensorflow.tensorboard --logdir=/tmp/logistic_logs"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Using Keras"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from keras.models import Sequential\n",
    "from keras.layers import Dense, Activation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "93 dims\n",
      "Building model...\n",
      "9 classes\n",
      "Epoch 1/10\n",
      "61878/61878 [==============================] - 3s - loss: 1.9845     \n",
      "Epoch 2/10\n",
      "61878/61878 [==============================] - 2s - loss: 1.8337     \n",
      "Epoch 3/10\n",
      "61878/61878 [==============================] - 2s - loss: 1.7779     \n",
      "Epoch 4/10\n",
      "61878/61878 [==============================] - 3s - loss: 1.7432     \n",
      "Epoch 5/10\n",
      "61878/61878 [==============================] - 2s - loss: 1.7187     \n",
      "Epoch 6/10\n",
      "61878/61878 [==============================] - 3s - loss: 1.7002     \n",
      "Epoch 7/10\n",
      "61878/61878 [==============================] - 2s - loss: 1.6857     \n",
      "Epoch 8/10\n",
      "61878/61878 [==============================] - 2s - loss: 1.6739     \n",
      "Epoch 9/10\n",
      "61878/61878 [==============================] - 2s - loss: 1.6642     \n",
      "Epoch 10/10\n",
      "61878/61878 [==============================] - 2s - loss: 1.6560     \n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<keras.callbacks.History at 0x123026dd8>"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dims = X_train.shape[1]\n",
    "print(dims, 'dims')\n",
    "print(\"Building model...\")\n",
    "\n",
    "nb_classes = Y_train.shape[1]\n",
    "print(nb_classes, 'classes')\n",
    "\n",
    "model = Sequential()\n",
    "model.add(Dense(nb_classes, input_shape=(dims,), activation='sigmoid'))\n",
    "model.add(Activation('softmax'))\n",
    "\n",
    "model.compile(optimizer='sgd', loss='categorical_crossentropy')\n",
    "model.fit(X_train, Y_train)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Simplicity is pretty impressive right? :)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Theano**:\n",
    "\n",
    "`shape = (channels, rows, cols)`\n",
    "\n",
    "**Tensorflow**:\n",
    "\n",
    "`shape = (rows, cols, channels)`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`image_data_format` : `channels_last | channels_first`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{\r\n",
      "\t\"epsilon\": 1e-07,\r\n",
      "\t\"backend\": \"tensorflow\",\r\n",
      "\t\"floatx\": \"float32\",\r\n",
      "\t\"image_data_format\": \"channels_last\"\r\n",
      "}\r\n"
     ]
    }
   ],
   "source": [
    "!cat ~/.keras/keras.json"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now lets understand:\n",
    "<pre>The core data structure of Keras is a <b>model</b>, a way to organize layers. The main type of model is the <b>Sequential</b> model, a linear stack of layers.</pre>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "What we did here is stacking a Fully Connected (<b>Dense</b>) layer of trainable weights from the input to the output and an <b>Activation</b> layer on top of the weights layer."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### Dense"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "```python\n",
    "from keras.layers.core import Dense\n",
    "\n",
    "Dense(units, activation=None, use_bias=True, \n",
    "      kernel_initializer='glorot_uniform', bias_initializer='zeros', \n",
    "      kernel_regularizer=None, bias_regularizer=None, \n",
    "      activity_regularizer=None, kernel_constraint=None, bias_constraint=None)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* `units`: int > 0.\n",
    "\n",
    "* `init`: name of initialization function for the weights of the layer (see initializations), or alternatively, Theano function to use for weights initialization. This parameter is only relevant if you don't pass a weights argument.\n",
    "\n",
    "* `activation`: name of activation function to use (see activations), or alternatively, elementwise Theano function. If you don't specify anything, no activation is applied (ie. \"linear\" activation: a(x) = x).\n",
    "\n",
    "* `weights`: list of Numpy arrays to set as initial weights. The list should have 2 elements, of shape (input_dim, output_dim) and (output_dim,) for weights and biases respectively.\n",
    "\n",
    "* `kernel_regularizer`: instance of WeightRegularizer (eg. L1 or L2 regularization), applied to the main weights matrix.\n",
    "\n",
    "* `bias_regularizer`: instance of WeightRegularizer, applied to the bias.\n",
    "\n",
    "* `activity_regularizer`: instance of ActivityRegularizer, applied to the network output.\n",
    "\n",
    "* `kernel_constraint`: instance of the constraints module (eg. maxnorm, nonneg), applied to the main weights matrix.\n",
    "\n",
    "* `bias_constraint`: instance of the constraints module, applied to the bias.\n",
    "\n",
    "* `use_bias`: whether to include a bias (i.e. make the layer affine rather than linear)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## (some) others `keras.core.layers`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* `keras.layers.core.Flatten()`\n",
    "* `keras.layers.core.Reshape(target_shape)`\n",
    "* `keras.layers.core.Permute(dims)`\n",
    "\n",
    "```python\n",
    "model = Sequential()\n",
    "model.add(Permute((2, 1), input_shape=(10, 64)))\n",
    "# now: model.output_shape == (None, 64, 10)\n",
    "# note: `None` is the batch dimension\n",
    "```\n",
    "\n",
    "* `keras.layers.core.Lambda(function, output_shape=None, arguments=None)`\n",
    "* `keras.layers.core.ActivityRegularization(l1=0.0, l2=0.0)`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"../imgs/dl_overview.png\" >\n",
    "\n",
    "Credits: Yam Peleg ([@Yampeleg](https://twitter.com/yampeleg))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### Activation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "```python\n",
    "from keras.layers.core import Activation\n",
    "\n",
    "Activation(activation)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Supported Activations** : [https://keras.io/activations/]\n",
    "\n",
    "**Advanced Activations**: [https://keras.io/layers/advanced-activations/]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### Optimizer"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you need to, you can further configure your optimizer. A core principle of Keras is to make things reasonably simple, while allowing the user to be fully in control when they need to (the ultimate control being the easy extensibility of the source code).\n",
    "Here we used <b>SGD</b> (stochastic gradient descent) as an optimization algorithm for our trainable weights.  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"http://sebastianruder.com/content/images/2016/09/saddle_point_evaluation_optimizers.gif\" width=\"40%\">\n",
    "\n",
    "Source & Reference: http://sebastianruder.com/content/images/2016/09/saddle_point_evaluation_optimizers.gif"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\"Data Sciencing\" this example a little bit more\n",
    "====="
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "What we did here is nice, however in the real world it is not useable because of overfitting.\n",
    "Lets try and solve it with cross validation."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### Overfitting"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In overfitting, a statistical model describes random error or noise instead of the underlying relationship. Overfitting occurs when a model is excessively complex, such as having too many parameters relative to the number of observations. \n",
    "\n",
    "A model that has been overfit has poor predictive performance, as it overreacts to minor fluctuations in the training data."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "<img src=\"../imgs/overfitting.png\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<pre>To avoid overfitting, we will first split out data to training set and test set and test out model on the test set.\n",
    "Next: we will use two of keras's callbacks <b>EarlyStopping</b> and <b>ModelCheckpoint</b></pre>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's see first the model we implemented"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "dense_1 (Dense)              (None, 9)                 846       \n",
      "_________________________________________________________________\n",
      "activation_1 (Activation)    (None, 9)                 0         \n",
      "=================================================================\n",
      "Total params: 846\n",
      "Trainable params: 846\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "model.summary()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from sklearn.model_selection import train_test_split\n",
    "from keras.callbacks import EarlyStopping, ModelCheckpoint"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 52596 samples, validate on 9282 samples\n",
      "Epoch 1/50\n",
      "52596/52596 [==============================] - 1s - loss: 1.6516 - val_loss: 1.6513\n",
      "Epoch 2/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6501 - val_loss: 1.6499\n",
      "Epoch 3/50\n",
      "52596/52596 [==============================] - 1s - loss: 1.6488 - val_loss: 1.6486\n",
      "Epoch 4/50\n",
      "52596/52596 [==============================] - 1s - loss: 1.6474 - val_loss: 1.6473\n",
      "Epoch 5/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6462 - val_loss: 1.6461\n",
      "Epoch 6/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6449 - val_loss: 1.6448\n",
      "Epoch 7/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6437 - val_loss: 1.6437\n",
      "Epoch 8/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6425 - val_loss: 1.6425\n",
      "Epoch 9/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6414 - val_loss: 1.6414\n",
      "Epoch 10/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6403 - val_loss: 1.6403\n",
      "Epoch 11/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6392 - val_loss: 1.6393\n",
      "Epoch 12/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6382 - val_loss: 1.6383\n",
      "Epoch 13/50\n",
      "52596/52596 [==============================] - 1s - loss: 1.6372 - val_loss: 1.6373\n",
      "Epoch 14/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6362 - val_loss: 1.6363\n",
      "Epoch 15/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6352 - val_loss: 1.6354\n",
      "Epoch 16/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6343 - val_loss: 1.6345\n",
      "Epoch 17/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6334 - val_loss: 1.6336\n",
      "Epoch 18/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6325 - val_loss: 1.6327\n",
      "Epoch 19/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6316 - val_loss: 1.6319\n",
      "Epoch 20/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6308 - val_loss: 1.6311\n",
      "Epoch 21/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6300 - val_loss: 1.6303\n",
      "Epoch 22/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6292 - val_loss: 1.6295\n",
      "Epoch 23/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6284 - val_loss: 1.6287\n",
      "Epoch 24/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6276 - val_loss: 1.6280\n",
      "Epoch 25/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6269 - val_loss: 1.6273\n",
      "Epoch 26/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6262 - val_loss: 1.6265\n",
      "Epoch 27/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6254 - val_loss: 1.6258\n",
      "Epoch 28/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6247 - val_loss: 1.6252\n",
      "Epoch 29/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6241 - val_loss: 1.6245\n",
      "Epoch 30/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6234 - val_loss: 1.6238\n",
      "Epoch 31/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6227 - val_loss: 1.6232\n",
      "Epoch 32/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6221 - val_loss: 1.6226\n",
      "Epoch 33/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6215 - val_loss: 1.6220\n",
      "Epoch 34/50\n",
      "52596/52596 [==============================] - 1s - loss: 1.6209 - val_loss: 1.6214\n",
      "Epoch 35/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6203 - val_loss: 1.6208\n",
      "Epoch 36/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6197 - val_loss: 1.6202\n",
      "Epoch 37/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6191 - val_loss: 1.6197\n",
      "Epoch 38/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6186 - val_loss: 1.6191\n",
      "Epoch 39/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6180 - val_loss: 1.6186\n",
      "Epoch 40/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6175 - val_loss: 1.6181\n",
      "Epoch 41/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6170 - val_loss: 1.6175\n",
      "Epoch 42/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6165 - val_loss: 1.6170\n",
      "Epoch 43/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6160 - val_loss: 1.6166\n",
      "Epoch 44/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6155 - val_loss: 1.6161\n",
      "Epoch 45/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6150 - val_loss: 1.6156\n",
      "Epoch 46/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6145 - val_loss: 1.6151\n",
      "Epoch 47/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6141 - val_loss: 1.6147\n",
      "Epoch 48/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6136 - val_loss: 1.6142\n",
      "Epoch 49/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6132 - val_loss: 1.6138\n",
      "Epoch 50/50\n",
      "52596/52596 [==============================] - 0s - loss: 1.6127 - val_loss: 1.6134\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<keras.callbacks.History at 0x11e7a2710>"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_train, X_val, Y_train, Y_val = train_test_split(X_train, Y_train, test_size=0.15, random_state=42)\n",
    "\n",
    "fBestModel = 'best_model.h5' \n",
    "early_stop = EarlyStopping(monitor='val_loss', patience=2, verbose=1) \n",
    "best_model = ModelCheckpoint(fBestModel, verbose=0, save_best_only=True)\n",
    "\n",
    "model.fit(X_train, Y_train, validation_data = (X_val, Y_val), epochs=50, \n",
    "          batch_size=128, verbose=True, callbacks=[best_model, early_stop]) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Multi-Layer Fully Connected Networks"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"../imgs/MLP.png\" width=\"45%\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Forward and Backward Propagation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"../imgs/backprop.png\" width=\"50%\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Q:** _How hard can it be to build a Multi-Layer Fully-Connected Network with keras?_\n",
    "\n",
    "**A:** _It is basically the same, just add more layers!_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "dense_2 (Dense)              (None, 100)               9400      \n",
      "_________________________________________________________________\n",
      "dense_3 (Dense)              (None, 9)                 909       \n",
      "_________________________________________________________________\n",
      "activation_2 (Activation)    (None, 9)                 0         \n",
      "=================================================================\n",
      "Total params: 10,309\n",
      "Trainable params: 10,309\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "model = Sequential()\n",
    "model.add(Dense(100, input_shape=(dims,)))\n",
    "model.add(Dense(nb_classes))\n",
    "model.add(Activation('softmax'))\n",
    "model.compile(optimizer='sgd', loss='categorical_crossentropy')\n",
    "model.summary()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 52596 samples, validate on 9282 samples\n",
      "Epoch 1/20\n",
      "52596/52596 [==============================] - 1s - loss: 1.2113 - val_loss: 0.8824\n",
      "Epoch 2/20\n",
      "52596/52596 [==============================] - 0s - loss: 0.8229 - val_loss: 0.7851\n",
      "Epoch 3/20\n",
      "52596/52596 [==============================] - 0s - loss: 0.7623 - val_loss: 0.7470\n",
      "Epoch 4/20\n",
      "52596/52596 [==============================] - 1s - loss: 0.7329 - val_loss: 0.7258\n",
      "Epoch 5/20\n",
      "52596/52596 [==============================] - 1s - loss: 0.7143 - val_loss: 0.7107\n",
      "Epoch 6/20\n",
      "52596/52596 [==============================] - 0s - loss: 0.7014 - val_loss: 0.7005\n",
      "Epoch 7/20\n",
      "52596/52596 [==============================] - 1s - loss: 0.6918 - val_loss: 0.6922\n",
      "Epoch 8/20\n",
      "52596/52596 [==============================] - 0s - loss: 0.6843 - val_loss: 0.6868\n",
      "Epoch 9/20\n",
      "52596/52596 [==============================] - 0s - loss: 0.6784 - val_loss: 0.6817\n",
      "Epoch 10/20\n",
      "52596/52596 [==============================] - 0s - loss: 0.6736 - val_loss: 0.6773\n",
      "Epoch 11/20\n",
      "52596/52596 [==============================] - 0s - loss: 0.6695 - val_loss: 0.6739\n",
      "Epoch 12/20\n",
      "52596/52596 [==============================] - 1s - loss: 0.6660 - val_loss: 0.6711\n",
      "Epoch 13/20\n",
      "52596/52596 [==============================] - 1s - loss: 0.6631 - val_loss: 0.6688\n",
      "Epoch 14/20\n",
      "52596/52596 [==============================] - 1s - loss: 0.6604 - val_loss: 0.6670\n",
      "Epoch 15/20\n",
      "52596/52596 [==============================] - 1s - loss: 0.6582 - val_loss: 0.6649\n",
      "Epoch 16/20\n",
      "52596/52596 [==============================] - 1s - loss: 0.6563 - val_loss: 0.6626\n",
      "Epoch 17/20\n",
      "52596/52596 [==============================] - 1s - loss: 0.6545 - val_loss: 0.6611\n",
      "Epoch 18/20\n",
      "52596/52596 [==============================] - 1s - loss: 0.6528 - val_loss: 0.6598\n",
      "Epoch 19/20\n",
      "52596/52596 [==============================] - 1s - loss: 0.6514 - val_loss: 0.6578\n",
      "Epoch 20/20\n",
      "52596/52596 [==============================] - 1s - loss: 0.6500 - val_loss: 0.6571\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<keras.callbacks.History at 0x12830b978>"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.fit(X_train, Y_train, validation_data = (X_val, Y_val), epochs=20, \n",
    "          batch_size=128, verbose=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Your Turn!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Hands On - Keras Fully Connected\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Take couple of minutes and try to play with the number of layers and the number of parameters in the layers to get the best results. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "dense_4 (Dense)              (None, 100)               9400      \n",
      "_________________________________________________________________\n",
      "dense_5 (Dense)              (None, 9)                 909       \n",
      "_________________________________________________________________\n",
      "activation_3 (Activation)    (None, 9)                 0         \n",
      "=================================================================\n",
      "Total params: 10,309\n",
      "Trainable params: 10,309\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "model = Sequential()\n",
    "model.add(Dense(100, input_shape=(dims,)))\n",
    "\n",
    "# ...\n",
    "# ...\n",
    "# Play with it! add as much layers as you want! try and get better results.\n",
    "\n",
    "model.add(Dense(nb_classes))\n",
    "model.add(Activation('softmax'))\n",
    "model.compile(optimizer='sgd', loss='categorical_crossentropy')\n",
    "\n",
    "model.summary()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 52596 samples, validate on 9282 samples\n",
      "Epoch 1/20\n",
      "52596/52596 [==============================] - 1s - loss: 1.2107 - val_loss: 0.8821\n",
      "Epoch 2/20\n",
      "52596/52596 [==============================] - 1s - loss: 0.8204 - val_loss: 0.7798\n",
      "Epoch 3/20\n",
      "52596/52596 [==============================] - 1s - loss: 0.7577 - val_loss: 0.7393\n",
      "Epoch 4/20\n",
      "52596/52596 [==============================] - 0s - loss: 0.7280 - val_loss: 0.7176\n",
      "Epoch 5/20\n",
      "52596/52596 [==============================] - 1s - loss: 0.7097 - val_loss: 0.7028\n",
      "Epoch 6/20\n",
      "52596/52596 [==============================] - 1s - loss: 0.6973 - val_loss: 0.6929\n",
      "Epoch 7/20\n",
      "52596/52596 [==============================] - 1s - loss: 0.6883 - val_loss: 0.6858\n",
      "Epoch 8/20\n",
      "52596/52596 [==============================] - 1s - loss: 0.6813 - val_loss: 0.6804\n",
      "Epoch 9/20\n",
      "52596/52596 [==============================] - 1s - loss: 0.6757 - val_loss: 0.6756\n",
      "Epoch 10/20\n",
      "52596/52596 [==============================] - 1s - loss: 0.6711 - val_loss: 0.6722\n",
      "Epoch 11/20\n",
      "52596/52596 [==============================] - 1s - loss: 0.6672 - val_loss: 0.6692\n",
      "Epoch 12/20\n",
      "52596/52596 [==============================] - 0s - loss: 0.6641 - val_loss: 0.6667\n",
      "Epoch 13/20\n",
      "52596/52596 [==============================] - 0s - loss: 0.6613 - val_loss: 0.6636\n",
      "Epoch 14/20\n",
      "52596/52596 [==============================] - 0s - loss: 0.6589 - val_loss: 0.6620\n",
      "Epoch 15/20\n",
      "52596/52596 [==============================] - 0s - loss: 0.6568 - val_loss: 0.6606\n",
      "Epoch 16/20\n",
      "52596/52596 [==============================] - 0s - loss: 0.6546 - val_loss: 0.6589\n",
      "Epoch 17/20\n",
      "52596/52596 [==============================] - 0s - loss: 0.6531 - val_loss: 0.6577\n",
      "Epoch 18/20\n",
      "52596/52596 [==============================] - 0s - loss: 0.6515 - val_loss: 0.6568\n",
      "Epoch 19/20\n",
      "52596/52596 [==============================] - 0s - loss: 0.6501 - val_loss: 0.6546\n",
      "Epoch 20/20\n",
      "52596/52596 [==============================] - 0s - loss: 0.6489 - val_loss: 0.6539\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<keras.callbacks.History at 0x1285bae80>"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.fit(X_train, Y_train, validation_data = (X_val, Y_val), epochs=20, \n",
    "          batch_size=128, verbose=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Building a question answering system, an image classification model, a Neural Turing Machine, a word2vec embedder or any other model is just as fast. The ideas behind deep learning are simple, so why should their implementation be painful?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Theoretical Motivations for depth"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    ">Much has been studied about the depth of neural nets. Is has been proven mathematically[1] and empirically that convolutional neural network benifit from depth! "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[1] - On the Expressive Power of Deep Learning: A Tensor Analysis - Cohen, et al 2015"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Theoretical Motivations for depth"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "One much quoted theorem about neural network states that:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    ">Universal approximation theorem states[1] that a feed-forward network with a single hidden layer containing a finite number of neurons (i.e., a multilayer perceptron), can approximate continuous functions on compact subsets of $\\mathbb{R}^n$, under mild assumptions on the activation function. The theorem thus states that simple neural networks can represent a wide variety of interesting functions when given appropriate parameters; however, it does not touch upon the algorithmic learnability of those parameters."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[1] - Approximation Capabilities of Multilayer Feedforward Networks - Kurt Hornik 1991"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Addendum\n",
    "\n",
    "[2.3.1 Keras Backend](2.3.1  Keras Backend.ipynb)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
